﻿Imports System
Imports System.Drawing
Imports System.Reflection
Imports System.Windows.Forms

''' <summary>
''' Wrapper over the control like TextBox.
''' </summary>
Public Class TextBoxWrapper
    Implements ITextBoxWrapper

    Private target As Control
    Private _selectionStart As PropertyInfo
    Private _selectionLength As PropertyInfo
    Private _selectedText As PropertyInfo
    Private readonlyProperty As PropertyInfo
    Private _getPositionFromCharIndex As MethodInfo
    Private Event RTBScroll As ScrollEventHandler

    Private Sub New(targetControl As Control)
        Me.target = targetControl
        Init()
    End Sub

    Protected Overridable Sub Init()
        Dim t = target.GetType()
        _selectedText = t.GetProperty("SelectedText")
        _selectionLength = t.GetProperty("SelectionLength")
        _selectionStart = t.GetProperty("SelectionStart")
        readonlyProperty = t.GetProperty("ReadOnly")
        _getPositionFromCharIndex = If(t.GetMethod("GetPositionFromCharIndex"), t.GetMethod("PositionToPoint"))

        If TypeOf target Is RichTextBox Then
            AddHandler CType(target, RichTextBox).VScroll, New EventHandler(AddressOf TextBoxWrapper_VScroll)
        End If
    End Sub

    Sub TextBoxWrapper_VScroll(sender As Object, e As EventArgs)
        RaiseEvent RTBScroll(sender, New ScrollEventArgs(ScrollEventType.EndScroll, 0, 1))
    End Sub

    Public Shared Function Create(targetControl As Control) As TextBoxWrapper
        Dim result As New TextBoxWrapper(targetControl)
        If result._selectedText Is Nothing OrElse result._selectionLength Is Nothing OrElse result._selectionStart Is Nothing OrElse result._getPositionFromCharIndex Is Nothing Then
            Return Nothing
        End If
        Return result
    End Function

    Public Overridable Property Text() As String Implements ITextBoxWrapper.Text
        Get
            Return target.Text
        End Get
        Set(value As String)
            target.Text = value
        End Set
    End Property

    Public Overridable Property SelectedText() As String Implements ITextBoxWrapper.SelectedText
        Get
            Return _selectedText.GetValue(target, Nothing)
        End Get
        Set(value As String)
            _selectedText.SetValue(target, value, Nothing)
        End Set
    End Property

    Public Overridable Property SelectionLength() As Integer Implements ITextBoxWrapper.SelectionLength
        Get
            Return _selectionLength.GetValue(target, Nothing)
        End Get
        Set(value As Integer)
            _selectionLength.SetValue(target, value, Nothing)
        End Set
    End Property

    Public Overridable Property SelectionStart() As Integer Implements ITextBoxWrapper.SelectionStart
        Get
            Return _selectionStart.GetValue(target, Nothing)
        End Get
        Set(value As Integer)
            _selectionStart.SetValue(target, value, Nothing)
        End Set
    End Property

    Public Overridable Function GetPositionFromCharIndex(pos As Integer) As Point Implements ITextBoxWrapper.GetPositionFromCharIndex
        Return _getPositionFromCharIndex.Invoke(target, New Object() {pos})
    End Function

    Public Overridable Function FindForm() As Form
        Return target.FindForm()
    End Function

    Public Custom Event LostFocus As EventHandler Implements ITextBoxWrapper.LostFocus
        AddHandler(ByVal value As EventHandler)
            AddHandler target.LostFocus, value
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            RemoveHandler target.LostFocus, value
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
            'RaiseEvent LostFocus(sender, e)
        End RaiseEvent
    End Event

    Public Custom Event Scroll As ScrollEventHandler Implements ITextBoxWrapper.Scroll
        AddHandler(ByVal value As ScrollEventHandler)
            If TypeOf target Is RichTextBox Then
                AddHandler RTBScroll, value
            ElseIf TypeOf target Is ScrollableControl Then
                AddHandler CType(target, ScrollableControl).Scroll, value
            End If
        End AddHandler
        RemoveHandler(ByVal value As ScrollEventHandler)
            If TypeOf target Is RichTextBox Then
                RemoveHandler RTBScroll, value
            ElseIf TypeOf target Is ScrollableControl Then
                RemoveHandler CType(target, ScrollableControl).Scroll, value
            End If
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As ScrollEventArgs)
            'RaiseEvent Scroll(sender, e)
        End RaiseEvent
    End Event

    Public Custom Event KeyDown As KeyEventHandler Implements ITextBoxWrapper.KeyDown
        AddHandler(ByVal value As KeyEventHandler)
            AddHandler target.KeyDown, value
        End AddHandler
        RemoveHandler(ByVal value As KeyEventHandler)
            RemoveHandler target.KeyDown, value
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As KeyEventArgs)
            'RaiseEvent KeyDown(sender, e)
        End RaiseEvent
    End Event

    Public Custom Event MouseDown As MouseEventHandler Implements ITextBoxWrapper.MouseDown
        AddHandler(ByVal value As MouseEventHandler)
            AddHandler target.MouseDown, value
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            RemoveHandler target.MouseDown, value
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As MouseEventArgs)
            'RaiseEvent MouseDown(sender, e)
        End RaiseEvent
    End Event

    Public Overridable ReadOnly Property TargetControl() As Control Implements ITextBoxWrapper.TargetControl
        Get
            Return target
        End Get
    End Property

    Public ReadOnly Property [ReadOnly]() As Boolean Implements ITextBoxWrapper.ReadOnly
        Get
            Return readonlyProperty.GetValue(target, Nothing)
        End Get
    End Property
End Class